package com.cainiao.stock.service.Impl;

import com.cainiao.stock.banner.BannerApplicationRunner;
import com.cainiao.stock.entity.StockBusiness;
import com.cainiao.stock.entity.StockMarketIndexInfo;
import com.cainiao.stock.entity.StockMarketLogPrice;
import com.cainiao.stock.entity.StockRtInfo;
import com.cainiao.stock.enums.CodeEnum;
import com.cainiao.stock.mapper.*;
import com.cainiao.stock.properties.MarketProperties;
import com.cainiao.stock.response.PageResult;
import com.cainiao.stock.response.ResponseResult;
import com.cainiao.stock.service.StockService;
import com.cainiao.stock.util.DateTimeUtil;
import com.cainiao.stock.vo.*;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.math.MathContext;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;



@Service
public class StockServiceImpl implements StockService {
    private final StockBusinessMapper stockBusinessMapper;
    private final MarketProperties marketProperties;
    private final StockMarketIndexInfoMapper stockMarketIndexInfoMapper;
    private final StockMarketLogPriceMapper stockMarketLogPriceMapper;
    private final StockBlockRtInfoMapper stockBlockRtInfoMapper;
    private final StockRtInfoMapper stockRtInfoMapper;
    private final BannerApplicationRunner bannerApplicationRunner;

    public StockServiceImpl(StockBusinessMapper stockBusinessMapper, MarketProperties marketProperties, StockMarketIndexInfoMapper stockMarketIndexInfoMapper, StockMarketLogPriceMapper stockMarketLogPriceMapper, StockBlockRtInfoMapper stockBlockRtInfoMapper, StockRtInfoMapper stockRtInfoMapper, BannerApplicationRunner bannerApplicationRunner) {
        this.stockBusinessMapper = stockBusinessMapper;
        this.marketProperties = marketProperties;
        this.stockMarketIndexInfoMapper = stockMarketIndexInfoMapper;
        this.stockMarketLogPriceMapper = stockMarketLogPriceMapper;
        this.stockBlockRtInfoMapper = stockBlockRtInfoMapper;
        this.stockRtInfoMapper = stockRtInfoMapper;
        this.bannerApplicationRunner = bannerApplicationRunner;
    }

    @Override
    public List<StockBusiness> getStockBusiness() {
        return stockBusinessMapper.selectAll();
    }

    @Override
    public List<InnerMarketVO> innerIndexAll() {
        // 1. 获取国内大盘指数编码集合
        List<String> ids=marketProperties.getInner();
        // 2. 获取最近的有效的股票交易时间
        LocalDateTime last = DateTimeUtil.getLastDateTime4Stock(LocalDateTime.now());
        // mock data
        String mockDate = "20211226105600";
        last=LocalDateTime.parse(mockDate, DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
        // 3. 查询
        // 3.1 根据大盘编码和日期查询 股票大盘数据详情表
        List<StockMarketIndexInfo> marketIndexInfoList= stockMarketIndexInfoMapper.selectByIdsAndDateTime(ids, last);
        // 3.2 根据大盘编码和日期查询 股票大盘 开盘价与前收盘价流水表
        LocalDate localDate=last.toLocalDate();
        List<StockMarketLogPrice> marketLogPricesList=stockMarketLogPriceMapper.selectByIdsAndDateTime(ids,localDate);
        //4. 组装数据
        return marketIndexInfoList.stream().map(
                (info)->{
                    InnerMarketVO vo=InnerMarketVO.builder()
                            .code(info.getMarkId())
                            .name(info.getMarkName())
                            .curDate(info.getCurTime().toLocalDate().toString())
                            .tradeAmt(info.getTradeAccount())
                            .tradeVol(info.getTradeVolume())
                            .tradePrice(info.getCurrentPrice())
                            .upDown(info.getUpdownRate())
                            .build();
                    marketLogPricesList.forEach((pricesInfo)->{
                        if(pricesInfo.getMarketCode().equals(info.getMarkId())){
                            vo.setOpenPrice(pricesInfo.getOpenPrice());
                            vo.setPreClosePrice(pricesInfo.getPreClosePrice());
                        }else {
                            vo.setOpenPrice(BigDecimal.ZERO);
                            vo.setPreClosePrice(BigDecimal.ZERO);
                        }
                    });
                    return vo;
                }
        ).toList();
    }

    @Override
    public ResponseResult<List<StockBlockRtInfoVO>> sectorAllLimit() {
        //1.调用mapper接口获取数据 TODO 优化 避免全表查询 根据时间范围查询，提高查询效率
        List<StockBlockRtInfoVO> infos=stockBlockRtInfoMapper.sectorAllLimit();
        //2.组装数据
        if (CollectionUtils.isEmpty(infos)) {
            return ResponseResult.error(CodeEnum.NO_RESPONSE_DATA);
        }
        return ResponseResult.ok(infos);
    }

    @Override
    public ResponseResult<List<StockRtInfoVO>> stockIncreaseLimit() {
        //1.直接调用mapper查询前10的数据 TODO 以时间顺序取前10
        //优化：
        //获取当前最近有效时间
        LocalDateTime last=DateTimeUtil.getLastDateTime4Stock(LocalDateTime.now());
        //mock数据
        String mockStr="2021-12-27 09:47:00";
        last=LocalDateTime.parse(mockStr, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        List<StockRtInfo> stockRtInfoList=stockRtInfoMapper.selectDateTime(last);
        List<StockRtInfoVO> result=new ArrayList<>();
        stockRtInfoList.stream().forEach((stock)->{
            StockRtInfoVO vo=new StockRtInfoVO();
            vo.setCode(stock.getStockCode());
            vo.setName(stock.getStockName());
            vo.setTradePrice(stock.getCurPrice());
            vo.setTradeAmt(Math.toIntExact(stock.getTradeAmount()));
            vo.setPreClosePrice(stock.getPreClosePrice());
            vo.setTradeVol(stock.getTradeVolume());
            vo.setCurDate(stock.getCurTime().toLocalDate().format(DateTimeFormatter.ofPattern("yyyyMMdd")));
            //涨跌
            BigDecimal upDown =stock.getCurPrice().subtract(stock.getPreClosePrice());
            //涨幅
            BigDecimal increase = upDown.divide(stock.getPreClosePrice(),new MathContext(6)).multiply(new BigDecimal(1.0));
            //振幅
            BigDecimal range=(stock.getMaxPrice().subtract(stock.getMinPrice())).divide(stock.getPreClosePrice(),new MathContext(6)).multiply(new BigDecimal(1.0));
            vo.setIncrease(increase);
            vo.setUpDown(upDown);
            vo.setAmplitude(range);
            result.add(vo);
        });
        List<StockRtInfoVO> list = result.stream().sorted((o1, o2) -> o2.getIncrease().compareTo(o1.getIncrease())).limit(10).toList();
        return ResponseResult.ok(list);
    }

    @Override
    public PageResult<MoreVO> more(Integer page,Integer pageSize) {
        LocalDateTime last=DateTimeUtil.getLastDateTime4Stock(LocalDateTime.now());
        LocalDateTime end=LocalDateTime.parse("2021-12-30 09:32:00",DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        Page<MoreVO> result= PageHelper.startPage(page,pageSize).doSelectPage(()->{
            List<MoreVO> voList=stockRtInfoMapper.selectMore(end);
        });
        return PageResult.<MoreVO>builder()
                .size(result.size())
                .totalPages(result.getPages())
                .totalRows(result.getTotal())
                .pageNum(result.getPageNum())
                .pageSize(result.getPageSize())
                .rows(result.getResult())
                .build();
    }

    @Override
    public UpdownVO upDown() {
        //1.获取股票最近的有效交易日期,精确到秒
        LocalDateTime curDateTime = DateTimeUtil.getLastDateTime4Stock(LocalDateTime.now());
        //当前最近有效期
        LocalDateTime begin = LocalDateTime.parse("2022-01-06 09:25:00",DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        LocalDateTime end = LocalDateTime.parse("2022-01-06 14:25:00",DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        //开盘日期
        List<UpdownVO.UpDownListBean> upList= stockRtInfoMapper.upDownCount(begin,end,true);
        List<UpdownVO.UpDownListBean> downList= stockRtInfoMapper.upDownCount(begin,end,false);
        return new UpdownVO(upList,downList);
    }

    @Override
    public TradevolVO tradevol() {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime t = DateTimeUtil.getLastDateTime4Stock(now);
        LocalDateTime t_open = DateTimeUtil.getOpenDate(t);
        LocalDateTime t_close = DateTimeUtil.getOpenDate(t);
        LocalDateTime t_1 = DateTimeUtil.getPreviousTradingDay(t);
        LocalDateTime t_1_open = DateTimeUtil.getOpenDate(t_1);
        LocalDateTime t_1_close = DateTimeUtil.getOpenDate(t_1);
        //TODO 后续注释掉 mock-data
        t_open = LocalDateTime.parse("2021-12-28 09:30:00", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        t_close = LocalDateTime.parse("2021-12-28 14:30:00", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        t_1_open = LocalDateTime.parse("2021-12-27 09:30:00", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        t_1_close = LocalDateTime.parse("2021-12-27 14:30:00", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        LocalDate localDate = t_open.toLocalDate();
        LocalDate localDate1 = t_1_open.toLocalDate();
        List<String> ids = marketProperties.getInner();
        List<TradevolVO.TradevolBean> list = stockMarketIndexInfoMapper.selectTradevol(t_1_open, t_close, ids);
        List<TradevolVO.TradevolBean> list1 = list.stream().filter(
                ts -> {
                    LocalDateTime paser = LocalDateTime.parse(ts.getTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                    LocalDate targetDate = paser.toLocalDate();
                    return targetDate.isEqual(localDate);
                }
        ).toList();
        List<TradevolVO.TradevolBean> list2 = list.stream().filter(
                t1s -> {
                    LocalDateTime paser = LocalDateTime.parse(t1s.getTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                    LocalDate targetDate = paser.toLocalDate();
                    return targetDate.isEqual(localDate1);
                }
        ).toList();
        return TradevolVO.builder()
                .volList(list1)
                .yesVolList(list2)
                .build();
    }

    @Override
    public StockUpDownVO stockUpdown() {
        //获取当前的时间
        LocalDateTime now=LocalDateTime.now();
        LocalDate localDate = now.toLocalDate();
        //mocke 模拟数据
        LocalDateTime mocke=LocalDateTime.parse("2022-01-06 09:55:00",DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        List<InfoVO> list= stockRtInfoMapper.selectStockUpdown(mocke);
        //todo 这里可以优化

        return StockUpDownVO.builder()
                .infos(list)
                .time(LocalDateTime.from(mocke))
                .build();

    }
}
